Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --pppd-call option. #270

Merged
merged 7 commits into from
Apr 3, 2018
Merged

Add --pppd-call option. #270

merged 7 commits into from
Apr 3, 2018

Conversation

gbon121
Copy link
Contributor

@gbon121 gbon121 commented Mar 30, 2018

On systems where pppd supports the "call" option --- eg. Debian derived
distros --- privileged options to pppd can be moved to a config file owned
by root, and any unprivileged user in group "dip" can invoke openfortivpn.

Static routes and DNS settings are managed by /etc/ppp/ip-up.local and
/etc/ppp/ip-down.local scripts, provided the following lines are added
to /etc/openfortivpn/config:

set-routes = 0
set-dns = 0
pppd-ipparam = openfortivpn
pppd-call = openfortivpn

On systems where pppd supports the "call" option --- eg. Debian derived
distros --- privileged options to pppd can be moved to a config file owned
by root, and any unprivileged user in group "dip" can invoke openfortivpn.

Static routes and DNS settings are managed by /etc/ppp/ip-up.local and
/etc/ppp/ip-down.local scripts, provided the following lines are added
to /etc/openfortivpn/config:

    set-routes = 0
    set-dns = 0
    pppd-ipparam = openfortivpn
    pppd-call = openfortivpn
Copy link
Collaborator

@DimitriPapadopoulos DimitriPapadopoulos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens to this piece of code when openfortivpn is called by an unprivileged user?
https://github.com/adrienverge/openfortivpn/blob/25b2585/src/tunnel.c#L126-L146

src/ipv4.c Outdated
snprintf(*target + l0, l1, fmt, dest, mask, gw);
} else {
int eno = errno;
log_error("Could not reallocate array: %s\n", strerror(eno));
Copy link
Collaborator

@DimitriPapadopoulos DimitriPapadopoulos Mar 30, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not that the message is any better this way, just for mere consistency with the rest of the code:

		log_error("realloc: %s\n", strerror(eno));

src/ipv4.c Outdated
*target = ptr;
snprintf(*target + l0, l1, fmt, dest, mask, gw);
} else {
int eno = errno;
Copy link
Collaborator

@DimitriPapadopoulos DimitriPapadopoulos Mar 30, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While log_error() may theoretically change the value of errno, for mere consistency with the rest of the code I suggest getting rid of eno and using errno directly.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually log_error() cannot change the value of errno before it is used as the strerror(errno) argument is evaluated before the function is called.

@DimitriPapadopoulos
Copy link
Collaborator

The man page should eventually be updated too: doc/openfortivpn.1.in

@gbon121
Copy link
Contributor Author

gbon121 commented Mar 31, 2018 via email

@DimitriPapadopoulos
Copy link
Collaborator

I must be missing something, but aren't all these options passed to pppd when they should be read from /etc/ppp/peers/openfortivpn instead?

		static const char *args[] = {
			pppd_path,
			"38400", // speed
			":1.1.1.1", // <local_IP_address>:<remote_IP_address>
			"noipdefault",
			"noaccomp",
			"noauth",
			"default-asyncmap",
			"nopcomp",
			"receive-all",
			"nodefaultroute",
			"nodetach",
			"lcp-max-configure", "40",
			"mru", "1354",
			NULL, // "usepeerdns"
			NULL, NULL, NULL, // "debug", "logfile", pppd_log
			NULL, NULL, // "plugin", pppd_plugin
			NULL, NULL, // "ipparam", pppd_ipparam
			NULL, NULL, // "ifname", pppd_ifname
			NULL // terminal null pointer required by execvp()
		};
		[...]
		execv(args[0], (char *const *)args);

@DimitriPapadopoulos
Copy link
Collaborator

Yes, I was definitely missing something! Perhaps some comments should be added to explain that --pppd-call overwrites the args array except for the pppd path.

@DimitriPapadopoulos
Copy link
Collaborator

I was thinking an if might be cleaner, something like this:

		if (tunnel->config->pppd_call) {
			...
		} else {
			...
		}

However I don't see how to initialize args and iin a more elegant way.

src/tunnel.c Outdated
@@ -145,6 +145,14 @@ static int pppd_run(struct tunnel *tunnel)
NULL // terminal null pointer required by execvp()
};

if (tunnel->config->pppd_call != NULL) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just write:

   	if (tunnel->config->pppd_call) {

Again I do not care myself but but the checkpatch.pl script of the Linux kernel emits a warning and we try to follow the Linux kernel coding style.

@DimitriPapadopoulos
Copy link
Collaborator

Looks good to me. Could you perhaps squash the commits so that I can merge your pull request?

@DimitriPapadopoulos
Copy link
Collaborator

DimitriPapadopoulos commented Apr 3, 2018

Does this mean openfortivpn will not need to be run by root anymore on Debian-based systems? If so this looks like a solution for issue #54. We should probably disable --pppd-plugin and --pppd-log when pppd is not run by root or at least emit a warning when these options are used. Does this make sense?

No need to address the above issue in this pull request, we shall handle it in a different pull request.

gbon121 added 2 commits April 3, 2018 14:27
On systems where pppd supports the "call" option --- eg. Debian derived
distros --- privileged options to pppd can be moved to a config file owned
by root, and any unprivileged user in group "dip" can invoke openfortivpn.

Static routes and DNS settings are managed by /etc/ppp/ip-up.local and
/etc/ppp/ip-down.local scripts, provided the following lines are added
to /etc/openfortivpn/config:

    set-routes = 0
    set-dns = 0
    pppd-ipparam = openfortivpn
    pppd-call = openfortivpn
On systems where pppd supports the "call" option --- eg. Debian derived
distros --- privileged options to pppd can be moved to a config file owned
by root, and any unprivileged user in group "dip" can invoke openfortivpn.

Static routes and DNS settings are managed by /etc/ppp/ip-up.local and
/etc/ppp/ip-down.local scripts, provided the following lines are added
to /etc/openfortivpn/config:

    set-routes = 0
    set-dns = 0
    pppd-ipparam = openfortivpn
    pppd-call = openfortivpn
@gbon121
Copy link
Contributor Author

gbon121 commented Apr 3, 2018

@DimitriPapadopoulos I'm not sure I squashed my commits properly. Should the PR result more difficult to merge than before, please let me know.

@DimitriPapadopoulos
Copy link
Collaborator

Actually you've added on more commit instead of replacing all existing commits by a single one, but don't worry: I can squash these commits myself not that I have the definitive comment (the one in the last commit).

@DimitriPapadopoulos DimitriPapadopoulos merged commit a2dfcb6 into adrienverge:master Apr 3, 2018
@gbon121
Copy link
Contributor Author

gbon121 commented Apr 11, 2018

@DimitriPapadopoulos I'm not sure the following code is more elegant of the current static array, but it might silence some warnings from Coverity:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

struct v_arr {
        /* current capacity */
        unsigned cap;
        /* next slot to write to, always < max(cap - 1, 1) */
        unsigned off;
        /* NULL terminated */
        void **data;
};

void append_v_arr(struct v_arr *p, void *x) {
        if (p->off + 1 >= p->cap) {
                void **ndata;
                unsigned ncap = (p->off + 1) * 2;
                assert(p->off + 1 < ncap);
                ndata = realloc(p->data, ncap * sizeof(void *));
                if (ndata) {
                        p->data = ndata;
                        p->cap = ncap;
                } else {
                        abort();
                }
        }
        assert(p->off + 1 < p->cap);
        p->data[p->off] = x;
        p->data[++p->off] = NULL;
}       

void clear_v_arr(struct v_arr *p) {
        free(p->data);
}
        
void use_array_of_char(const char **arr) { 
        const char **p;
        printf("result:");
        for (p = arr; *p; ++p) 
                printf(" %s", *p);
        printf("\n"); 
}               
        
int main() {
        const char *frag[] = { "pppd", "option1", "option2", "option3" };
        struct v_arr v = { 0, 0, 0 };
        unsigned i; 
        for (i = 0; i < sizeof frag / sizeof *frag; i++)
                append_v_arr(&v, (void *)frag[i]);
        use_array_of_char((const char **)v.data);
        clear_v_arr(&v);
        return 0;
}       

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants